package com.yjh.admin.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.ServerErrorException;
import org.springframework.web.servlet.NoHandlerFoundException;
import util.R;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@RestControllerAdvice
@Slf4j
public final class ExceptionAdviceHandler {

    private final static String SERVER_ERROR_TXT = "服务器内部错误";
    private final static String ARGUMENTS_ERROR_TXT = "参数错误";
    private final static String BAD_REQUEST_TXT = "错误的请求";

    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R unKnowExceptionHandler(Exception ex) {
        return this.serverErrorHandler(ex);
    }

    @ExceptionHandler(value = RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R runtimeExceptionHandler(RuntimeException ex) {
        return this.serverErrorHandler(ex);
    }

    /**
     * 空指针异常
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R nullPointerExceptionHandler(Exception e) {

        e.printStackTrace();

        return this.serverErrorHandler(e);
    }

    /**
     * 类型转换异常
     */
    @ExceptionHandler(ClassCastException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R classCastExceptionHandler(ClassCastException ex) {
        return this.serverErrorHandler(ex);
    }

    /**
     * IO异常
     */
    @ExceptionHandler(IOException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R iOExceptionHandler(IOException ex) {
        return this.serverErrorHandler(ex);
    }

    /**
     *  未知方法异常
     */
    @ExceptionHandler(NoSuchMethodException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R noSuchMethodExceptionHandler(NoSuchMethodException ex) {
        return this.serverErrorHandler(ex);
    }

    /**
     * 数组越界异常
     */
    @ExceptionHandler(IndexOutOfBoundsException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
        return this.serverErrorHandler(ex);
    }

    /**
     * 400错误
     */
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R requestNotReadable(HttpMessageNotReadableException ex) {
        return new R<>(400, BAD_REQUEST_TXT);
    }

    /**
     * 400错误 类型不匹配
     */
    @ExceptionHandler({TypeMismatchException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R requestTypeMismatch(TypeMismatchException ex) {
        return this.argumentsError();
    }

    /**
     * 400错误 缺少参数
     */
    @ExceptionHandler({MissingServletRequestParameterException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R requestMissingServletRequest() {
        return this.argumentsError();
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R methodArgumentNotValidExceptionHandler() {
        return new R<>(400,"参数错误");
    }

//    @ExceptionHandler(value = NotAuthorityException.class)
//    @ResponseStatus(HttpStatus.UNAUTHORIZED)
//    public SimpleResponse notAuthority(NotAuthorityException ex) {
//        return this.authErrorHandler(2, ex.getMessage());
//    }

    @ExceptionHandler(UsernameNotFoundException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R usernameNotFound(UsernameNotFoundException ex){
        return new R<>(400,ex.getMessage());

    }


//    @ExceptionHandler(value = NotAuthException.class)
//    @ResponseStatus(HttpStatus.UNAUTHORIZED)
//    public SimpleResponse notAuth(NotAuthException ex) {
//        return this.authErrorHandler(1, ex.getMessage());
//    }

//    @ExceptionHandler(value = AuthFailureException.class)
//    @ResponseStatus(HttpStatus.UNAUTHORIZED)
//    public SimpleResponse authFieald(AuthFailureException ex) {
//        return this.authErrorHandler(1, ex.getMessage());
//    }


    /**
     * 405错误
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public R request405(HttpRequestMethodNotSupportedException resp) {
        return this.serverErrorHandler(resp);
    }

    /**
     * 406错误
     */

//    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
//    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
//    public BaseResponse request406(HttpServletResponse resp) {
//        return baseResponse(405, "不接受该请求");
//
//    }

    /**
     * 500错误
     */
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R server500(HttpServletResponse resp,Exception e) {
        return this.serverErrorHandler(e);
    }

    @ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    public R httpMediaTypeNotSupportedExceptionHandler(HttpServletResponse resp) {
        return new R<>(415, "服务器无法处理请求附带的媒体格式");
    }


//    @ExceptionHandler(value = ArgumentsFailureException.class)
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    public BaseResponse argsErrorExceptionHandler(ArgumentsFailureException ex, HttpServletResponse response) {
//        return baseResponse(400, ex.getMessage());
//    }

    /**
     * 404
     */
    @ExceptionHandler(value = NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public R notFoundException(HttpServletResponse response) {
        return new R<>(404, "找不到服务");
    }

    @ExceptionHandler(value = ServerErrorException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R serverErrorExceptionHandler(HttpServletResponse response,ServerErrorException ex) {
        return this.serverErrorHandler(ex);
    }


    private R serverErrorHandler(Exception e) {
        e.printStackTrace();
        return new R<>(null, SERVER_ERROR_TXT,500);
    }

    private R argumentsError() {
        return new R<>(null, ARGUMENTS_ERROR_TXT,400);
    }

    /**
     * @param code 1 认证错误（未认证）、2 未授权/没有权限
     * @param msg
     * @return
     */
    private R authErrorHandler(int code, String msg) {
        return new R<>(400, ARGUMENTS_ERROR_TXT);
    }

}
